home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / mail / listserv / utils / list_stats.pl.Z / list_stats.pl
Encoding:
Perl Script  |  1994-05-04  |  6.0 KB  |  214 lines

  1. #!/usr/public/bin/perl
  2. #
  3. # From: Carl Paukstis <carlp@onpmomma.isc-br.com>
  4. #
  5. # Here's a PERL script I wrote to generate some statistics by subscriber
  6. # for some of my mailing lists.  Feel free to improve it (send me
  7. # improvements please) and/or hack it to better meet your needs.
  8. #
  9. # Gather ListProcessor mailing list statistics by subscriber from archive file.
  10. # Statistics are for one month, specified on the command-line.  The script
  11. # implicity assumes (and handles) "permissive" list mode, where messages are
  12. # not necessarily from addresses which can be found in the .subscribers file.
  13. #
  14. # Usage: stats.pl listname mont
  15. #
  16. #  Written December, 1993 by Carl Paukstis  carlp@mail.spk.olivetti.com
  17. #
  18. #  Released to the public domain.  Please credit the author.
  19. #  The author does NOT consider himself a PERL wizard, please send
  20. #  suggestions to the address above.
  21. #
  22. #  NOTE: created with 4-column tabs!
  23. #
  24. # This script has been tested with Unix ListProcessor v6.0b. running on
  25. # Olivetti Unix SysVr4 with mail handled by smail v3.  There may be
  26. # dependencies on mail-header formats which are peculiar to smail.
  27. # Created and tested with Perl 4.0.1.8 patchlevel 36
  28. #
  29. eval "exec /usr/public/bin/perl -S $0 $*"
  30.     if $running_under_some_shell;
  31.  
  32. chdir("/home/listproc") || die "can't change to listproc home dir; stopped";
  33.  
  34. @monames = ("Jan","Feb","Mar","Apr","May","Jun",
  35.             "Jul","Aug","Sep","Oct","Nov","Dec");
  36. $err=0;
  37. if (@ARGV == 2) {
  38.     $listname = $ARGV[0];
  39.     $listname =~ tr/[a-z]/[A-Z]/;            # uppercase listname
  40.     $month = $ARGV[1];
  41.     if ($month =~ /^[0-9]+$/)                 # convert month number to name
  42.         { $month = $monames[$month - 1]; }
  43.     substr($month,3,99) = "";                # make month 3-char string
  44.     substr($month,0,1) =~ tr/[a-z]/[A-Z]/;    # first char uppercase
  45.     substr($month,1,2) =~ tr/[A-Z]/[a-z]/;    # remaining chars lowercase
  46. } else { 
  47.     ++$err; }
  48. if (! -d "lists/$listname") { ++$err; }        # list-directory absent?
  49.  
  50. ++$err;                                        # "prime" error-counter...
  51. foreach $mon(@monames) {
  52.     $month eq $mon && --$err;                # ...then undo if month is valid
  53. }
  54. if ($err) {
  55.     print "Usage: stats.pl list-name month\n";
  56.     exit 2;
  57. }
  58.  
  59. #
  60. #  Change the following to control input and output files.
  61. #
  62. $sub="lists/$listname/.subscribers";
  63. $ali="lists/$listname/.aliases";
  64. $mbox="lists/$listname/archive";
  65. $destfile="|sort -n >/tmp/stats.$listname";
  66.  
  67. #
  68. #  Build assoc-arrays for all subscribers
  69. #
  70. open(SUB,$sub) || die "Can't open $sub, stopped";
  71. while(<SUB>) {
  72.     chop;
  73.     ($addr,$mode,$pw,$conceal,$name) = split(/[\t\n ]+/,$_,5);
  74. #    printf("'%s' %9s %-37s\n",$addr,$mode,$name);
  75.     $bytes{$addr} = 0;
  76.     $lines{$addr} = 0;
  77.     $msgs{$addr} = 0;
  78.     $flag{$addr} = 1;
  79.     $names{$addr} = $name;
  80. }
  81. close(SUB);
  82. #
  83. #  Point aliased subscribers to the "real" address
  84. #
  85. open(ALI,$ali) || die "Can't open $ali, stopped";
  86. while(<ALI>) {
  87.     chop;
  88.     ($addr,$alias) = split(/[\t\n ]+/,$_,2);
  89.     if ($flag{$alias} != 1) {
  90.         print "No match for alias $alias\n";
  91.     }
  92.     $flag{$addr} = 2;
  93.     $aliases{$addr} = $alias;
  94. #    printf("'%s' (alias %s) = %s\n",$addr,$alias,$names{$alias});
  95. }
  96. close(ALI);
  97.  
  98. #
  99. #  Spin through message archive; collect stats fo each sending address.
  100. #
  101. $new = 0;
  102. $skipped = 0;
  103. open(MBOX,$mbox) || die "Can't open $mbox, stopped";
  104. while(<MBOX>) {
  105.     if (/^From /) {                 # new mail-message
  106.         $new = 1;
  107.         ++$totmsgs;
  108.         chop;
  109.         ($first, $addr, $weekday, $msgmonth, $rest) = split(/[\t\n ]+/,$_,5);
  110.         $addr =~ tr/a-z/A-Z/;
  111.         if($addr=~/.*DAEMON.*/ || $addr=~/.*UUCP.*/ || $msgmonth ne $month) {
  112.             ++$skipped;                # ignore bogus senders
  113.             while(<MBOX>) {
  114.                 last if (/^From /);
  115.                 }
  116.             redo;
  117.         }
  118.         if($flag{$addr} == 0) {
  119.             $flag{$addr} = 3;        # unknown addr; get info from "From:" line
  120.         }
  121.         if($flag{$addr} == 2) {        # aliased user; use alias for data-collect
  122.             $addr = $aliases{$addr};
  123.         }
  124.         ++$msgs{$addr};
  125. #        printf("'%s' %4d\n",($names{$addr}) ? $names{$addr} : $addr,$msgs{$addr});
  126.     }
  127.     elsif (/^From: / && $flag{$addr} == 3) {    # for non-subscribers
  128.         $flag{$addr} = 1;
  129.         chop;
  130.         s/From:\s+//;                    # strip front of line
  131.         s/\s+$//;                        # and training whitespace
  132.         $line = $_;
  133.         if (/\((.*)\)/) {                # From: user@node (name here)
  134. #            print "matched parens\n";
  135.             $name = $1;
  136.         }
  137.         elsif (/<(.*)>/) {                # From: "name here" <user@node>
  138. #            print "matched anglebrackets\n";
  139.             s/\s*<.*$//;
  140.             s/"//g;
  141.             $name = $_;
  142.         }
  143.         else {
  144.             $name = "-no name given-";
  145.         }
  146.         $bytes{$addr} = 0;
  147.         $lines{$addr} = 0;
  148.         $msgs{$addr} = 1;
  149.         $flag{$addr} = 1;
  150.         $names{$addr} = $name;
  151.         print "No sub '$addr' ($name)\n";
  152.     }
  153.     elsif (/^\s*$/ && $new == 1) {    # first blank line after "From " 
  154.         $new = 0;
  155.     }
  156.     elsif ($new == 0) {                # body of message
  157.         ++$lines{$addr};
  158.         $bytes{$addr} += length;
  159.     }
  160.         
  161. }
  162. close(MBOX);
  163. print "Total messages $totmsgs; skipped $skipped extraneous messages\n";
  164. #
  165. #  Output the report from the statistics arrays.
  166. #  A couple of compromises were made in the formats to assure that the
  167. #  output could be fed to 'sort -n' and come out looking decent.
  168. #
  169. open(REPORT,"$destfile");
  170. select(REPORT);
  171. $^="RT";
  172. $|=1;
  173. $= =999999;
  174. $totmsgs = 0;
  175. $totbytes = 0;
  176. $totlines = 0;
  177.  
  178. foreach $addr(keys(%msgs)) {
  179.     if ($msgs{$addr}) {                    # do only subscribers with >0 messages
  180.         write;
  181.         $totmsgs += $msgs{$addr};
  182.         $totbytes += $bytes{$addr};
  183.         $totlines += $lines{$addr};
  184.     }
  185. }
  186. $addr = "----------";
  187. $names{$addr} ="<--- TOTAL";
  188. $msgs{$addr} = $totmsgs;
  189. $lines{$addr} = $totlines;
  190. $bytes{$addr} = $totbytes;
  191. write;
  192.  
  193. # This is the end of the actual program.
  194.  
  195. format RT =
  196. -                Statistics for @||||||||| for @<<
  197.                                 $listname,     $month
  198. -Msgs  Lines  Bytes        Sender                     Address
  199.  
  200.  
  201. format REPORT =
  202. @>>>> @>>>>> @>>>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  203. $msgs{$addr},$lines{$addr},$bytes{$addr},($names{$addr}) ? $names{$addr}:$addr, $addr
  204. ----------------------------- cut here -------------------------------
  205. -- 
  206. Carl Paukstis, RRR&RSG   DoD#0432 1KQSPI=8.80   carlp@mail.spk.olivetti.com
  207. Olivetti North America                          carlp@mom.isc-br.com
  208. (Oli North): will deny responsibility    voice: (509) 927-5439 0700-1600 M-F
  209. Spokane, Washington, USA                   FAX: (509) 927-2499 24 hrs.
  210.  
  211.